<?php

namespace App\Recharge\Api;

use App\Models\H5CombinedOrders;
use App\Models\InterfaceConfiguration;
use App\Recharge\Bean\ApiNotifyDataBean;
use App\Recharge\Bean\BasicInformation;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class Beileide extends AbstractApi
{

    /**
     * @inheritDoc
     */
    public function rechargeData(BasicInformation $bean): array
    {
        $key =$bean->getSecretKey(); // 密钥，通常应该是16字节长（AES-128）
        $iv = $bean->getSecretKey(); // IV，通常应该是16字节长，且随机且与密钥不同
        $array = [
            'partner_id'=> $bean->getSupplierNum(),//商户号
            'bill_id'=>$bean->getOrderNo(), //订单号
            'card_kind'=>$bean->getProductId(),
            'time_stamp'=>date('YmdHis',time()),
            'product_num'=>$bean->getRechargeNum(),
            'product_code'=>$bean->getGoodsId(),//商品编码
            'bill_time'=>date('YmdHis',time()),
        ];
        $key = substr($key, 0, 16);
        $iv = substr($iv, 0, 16);
        $data = json_encode($array);
        $encrypted = openssl_encrypt($data, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $encryptedBase64 = $this->encodeBytes($encrypted);
        return [
            'partner_id'=>$array['partner_id'],
            'bill_id'=>$array['bill_id'],
            'card_kind'=>$array['card_kind'],
            'time_stamp'=>$array['time_stamp'],
            'sign'=>$encryptedBase64,
            'product_num'=>$array['product_num'],
            'product_code'=>$array['product_code'],
            'bill_time'=>$array['bill_time'],
        ];
    }

    /**
     * @param InterfaceConfiguration $api
     * @param Request $request
     * @return ApiNotifyDataBean
     */
    public function apiNotifyLogic(InterfaceConfiguration $api, Request $request): ApiNotifyDataBean
    {
        $status = $request->input('Status', '');
        $order_sn = $request->input('OrderNo', '');
        $cami = '';
        if ($status == 1){
            if (empty($request->input('card_no_data', ''))){
                return
                    $this->apiNotifyData($order_sn, $status)
                    ->setExecute(true)
                    ->setRechargeSuccess($status == 1)
                    ->setCami('订单成功但是没有返回卡号');
            }
            $goods_belong = H5CombinedOrders::query()->where('trade_no',$order_sn)->value('supplier_status');
            Log::info($goods_belong);
            $user_data = InterfaceConfiguration::query() -> firstWhere('id',$goods_belong)->toArray();
            if (empty($user_data)){
                return $this->apiNotifyData($order_sn, $status)
                    ->setExecute(true)
                    ->setRechargeSuccess($status == 1)
                    ->setCami('第三方密钥不存在,解密失敗');
            }
            $cami = $this->decode_cami($request->input('card_no_data', ''),$user_data['iv']);
        }
        return $this
            ->apiNotifyData($order_sn, $status)
            ->setExecute(true)
            ->setRechargeSuccess($status == 1)
            ->setCami($cami)
            ->setRechargeErrorMessage($request->input('msg', ''));
    }

    /**
     * @param $bytes
     * @return string
     */
    public function encodeBytes($bytes): string
    {
        $result = '';
        $length = strlen($bytes);
        for ($i = 0; $i < $length; $i++) {
            // 获取当前字节的高四位（0-15）
            $highNibble = (ord($bytes[$i]) >> 4) & 0x0F;
            // 获取当前字节的低四位（0-15）
            $lowNibble = ord($bytes[$i]) & 0x0F;
            // 将高四位和低四位转换为字符 'a' 到 'p'
            $result .= chr($highNibble + ord('a'));
            $result .= chr($lowNibble + ord('a'));
        }
        return $result;
    }

    /**
     * @param string $encodedString
     * @return string
     */
    public function decodeBytes(string $encodedString): string
    {
        $result = '';
        $length = strlen($encodedString);
        // 确保字符串长度为偶数，因为每个字节被编码为两个字符
        if ($length % 2 != 0) {
            throw new \Exception('Invalid encoded string length');
        }
        for ($i = 0; $i < $length; $i += 2) {
            // 获取高四位对应的字符并转换为数值
            $highNibbleChar = $encodedString[$i];
            $highNibble = ord($highNibbleChar) - ord('a');
            // 获取低四位对应的字符并转换为数值
            $lowNibbleChar = $encodedString[$i + 1];
            $lowNibble = ord($lowNibbleChar) - ord('a');
            // 将高四位和低四位组合成一个字节
            $decodedByte = ($highNibble << 4) | $lowNibble;
            // 将字节添加到结果字符串中
            $result .= chr($decodedByte);
        }
        return $result;
    }

    /**
     * @param $cami
     * @param $key
     * @return string
     */
    public function decode_cami($cami,$key):string
    {
        $key = substr($key, 0, 16);
        $encrypted = $this->decodeBytes($cami);
        $cami =  json_decode(openssl_decrypt($encrypted, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $key), true);
        Log::error($cami);
        $cami = explode(',',$cami['card_no']);
        $cami_arr = ['sku_one'=>$cami[0], 'sku_two'=>$cami[1], 'sku_three'=>$cami[2] ?? 'null',];
        return json_encode($cami_arr);
    }

    /**
     * @return mixed
     */
    public function apiNotifySuccess(): mixed
    {
        return response('{"code":"200"}');
    }
}
